package com.bw.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisUtil {
	private String host = "localhost";
	private Integer port = 6379;
	private JedisPool pool = null;
	private Jedis jedis = null;
	
	public RedisUtil(String pwd)
	{
		pool = new JedisPool(host,port);
		auth(pwd);
	}
	
	public RedisUtil(String host,Integer port,String pwd)
	{
		this.host = host;
		this.port = port;
		pool = new JedisPool(host,port);
		auth(pwd);
	}
	
	public void close()
	{
		if(pool != null)
			pool.destroy();
	}
	
	public void auth(String pwd)
	{
		jedis = pool.getResource();
		if(pwd != null && !"".equals(pwd))
			jedis.auth(pwd);
	}
	
	/**
	 * 判断Jedis对象是否为空
	 */
	public boolean checkJedis()
	{
		if(jedis == null)
		{
			System.out.println("jedis对象为空，请首先调用auth(pwd),\r\n如果Redis服务器设置密码登录,pwd 为Redis的密码；\r\n如果Redis服务器未设置目录，pwd为null");
			return false;
		}
		return true;
	}
	
	/**
	 * 判断Redis是否存在Key
	 * @param key
	 * @return
	 */
	public boolean isExist(String key)
	{
		if(!checkJedis())
		{
			return false;
		}
		return jedis.exists(key);
	}
	
	
	
	/**
	 * 向Redis中新建String类型的Key-Value
	 * 存储的数据为Java的Object类型
	 * @param key
	 * @param obj
	 */
	public void setObject(String key,Object obj)
	{
		if(!checkJedis())
		{
			return;
		}
		//将obj对象序列化为字节数组
		byte[] data = getDataByte(obj);
		System.out.println("data=="+data+",jedis="+jedis);
		jedis.set(key.getBytes(), data);
	}
	
	/**
	 * 从Redis中读取字节数组并封装为Java对象
	 * @param key
	 * @return
	 */
	public Object getObject(String key)
	{
		if(!checkJedis())
		{
			return null;
		}
		byte[] data = jedis.get(key.getBytes());
		return getObject(data);
	}
	
	/**
	 * 向Redis中新建Map类型的Key-Value
	 * @param rkey Redis定义的Key
	 * @param mkey 数据中定义的Key
	 * @param val 数据中定义的Value
	 */
	public void setMapKey(String rkey,String mkey,String val)
	{
		if(!checkJedis())
		{
			return;
		}
		Map m = new HashMap();
		m.put(mkey, val);
		jedis.hmset(rkey, m);
	}
	
	/**
	 * 从Redis中读取Hash类型的Key-Value
	 * @param rkey Redis定义的Key
	 * @param mkey 数据中定义的Key
	 * @return
	 */
	public String getMapKey(String rkey,String mkey)
	{
		if(!checkJedis())
		{
			return null;
		}
		return jedis.hget(rkey, mkey);
	}
	
	/**
	 * 将Java的Map对象存放到Redis中Hash类型的Key-Value
	 * @param rkey Redis定义的Key
	 * @param m 数据对象Map
	 */
	public void setMapKey(String rkey,Map m)
	{
		if(!checkJedis())
		{
			return;
		}
		//需要将Java的Map对象中所有元素转换为byte[]
		Map<byte[],byte[]> m2 = new HashMap<byte[],byte[]>();
		for(Object key:m.keySet())
		{
			byte[] keyData = getDataByte(key);
			Object val = m.get(key);
			byte[] valData = getDataByte(val);
			m2.put(keyData, valData);
		}
		jedis.hmset(rkey.getBytes(), m2);
	}
	
	/**
	 * 通过Key读取Redis中Hash类型Key-Value
	 * @param rkey Redis定义的Key
	 * @return
	 */
	public Map getMapKey(String rkey)
	{
		if(!checkJedis())
		{
			return null;
		}
		//从Redis中获取的Map所有元素都是byte[]类型，需要反序列化为Java对象
		Map<byte[],byte[]> m = jedis.hgetAll(rkey.getBytes());
		Map rtn = new HashMap();
		for(byte[] data:m.keySet())
		{
			//反序列化Key
			Object key = getObject(data);
			byte[] valdata = m.get(data);
			//反序列化Value
			Object val = getObject(valdata);
			//返回的Map对象中所有元素为Java的Object类型
			rtn.put(key, val);
		}
		return rtn;
	}
	
	/**
	 * 将Java对象序列化为字节数组
	 * @param obj
	 * @return
	 */
	private byte[] getDataByte(Object obj)
	{
		try
		{
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(obj);
			byte[] data = baos.toByteArray();
			baos.close();
			return data;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 将字节数组反序列化为Java对象
	 * @param data
	 * @return
	 */
	private Object getObject(byte[] data)
	{
		try
		{
			ByteArrayInputStream bais = new ByteArrayInputStream(data);
			ObjectInputStream ois = new ObjectInputStream(bais);
			Object obj = ois.readObject();
			bais.close();
			return obj;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	public static void main(String[] args)
	{
		RedisUtil redis = new RedisUtil("192.168.25.30",6380,null);
		redis.setObject("obj1","Java");
		redis.close();
	}
}
